package com.tr.rts.spark.avro

import java.util

import com.tr.parser.{ExprSyntaxBaseVisitor, ExprSyntaxParser}
import com.tr.rts.spark.avro.AnnotatedTree.operations
import org.antlr.v4.runtime.tree.TerminalNode
import org.apache.avro.generic.GenericRecord
import org.apache.spark.rdd.RDD
import shaded.org.antlr.v4.runtime.tree.TerminalNode

import scala.collection.JavaConverters._
import scala.collection.mutable

case class Operation(  operation:String,  argList: util.List[String])
{

}



object AnnotatedTree {
    private var operations = new mutable.ListBuffer[Operation]();
    private var logicalOpStack = new mutable.Stack[String]();

    def pushLogicalOp(logicalOp: String):Unit ={
        logicalOpStack.push(logicalOp)
    }
    def popLogicalOp( ):Unit ={
        logicalOpStack.pop()
    }

    def add (operation:Operation) :Unit = {
        //val logicalOp = logicalOpStack.top
        //if(logicalOp.equalsIgnoreCase("AND"))
            operations.append(operation)
        //else if(logicalOp.equalsIgnoreCase("OR"))
        //    operations.prepend(operation)
    }

}

class ASTEvaluator (val tree:ExprSyntaxParser.ExpressionContext ) extends ExprSyntaxBaseVisitor [Any] {
    private var operations = new mutable.ListBuffer[Operation]();
    private var logicalOpStack = new mutable.Stack[String]();

    def add (operation:Operation) :Unit = {
        //val logicalOp = logicalOpStack.top
        //if(logicalOp.equalsIgnoreCase("AND"))
        operations.append(operation)
        //else if(logicalOp.equalsIgnoreCase("OR"))
        //    operations.prepend(operation)
    }
    def getOperations():List[Operation] = {
          operations.toList
    }
    override def visitExpression(ctx: ExprSyntaxParser.ExpressionContext): Any = {
        if (ctx.functionCall != null)
        {
           return  visitFunctionCall (ctx.functionCall)
        }
        else  if (ctx.op != null) {
            if (ctx.AND != null) {
                 //AnnotatedTree.pushLogicalOp("AND")
                 visitExpression (ctx.expression (0) )
                 visitExpression (ctx.expression (1) )
                 //AnnotatedTree.popLogicalOp()
            }
            else if (ctx.OR != null) {
               // AnnotatedTree.pushLogicalOp("OR")
                visitExpression (ctx.expression (0) )
                visitExpression (ctx.expression (1) )
                //AnnotatedTree.popLogicalOp()
            }
        }
        else  if (ctx.LP != null && ctx.RP != null) {
            return  visitExpression (ctx.expression (0) )
        }
        return null;
    }

    /**
      * {@inheritDoc }
      *
      * <p>The default implementation returns the result of calling
      * {@link #visitChildren} on {@code ctx}.</p>
      */
    override def visitFunctionCall(ctx: ExprSyntaxParser.FunctionCallContext): Any = {
        var terminalNode = ctx.GROUPBY
        if (terminalNode != null) {
            val argNodeList = ctx.functionArgs.field_name
            var argList = new util.ArrayList[ String]
            for( a <- 0 to argNodeList.size()){
                var arg = argNodeList.get(a).TEXT_STRING().getText
                //val path =  arg.split(".").toList.asJava
                argList.add(arg)
            }
            add( new Operation("map",argList))

        }

        terminalNode = ctx.MAX
        if (terminalNode != null) {
            val argNodeList = ctx.functionArgs.field_name
            var argList = new util.ArrayList[ String]
            for( a <- 0 to argNodeList.size()){
                var arg = argNodeList.get(a).TEXT_STRING().getText
                //val path =  arg.split(".").toList.asJava
                argList.add(arg)
            }
            add(  new Operation("maxby",argList))
        }

        terminalNode = ctx.MIN
        if (terminalNode != null) {
            val argNodeList = ctx.functionArgs.field_name
            var argList = new util.ArrayList[ String]
            for( a <- 0 to argNodeList.size()){
                var arg = argNodeList.get(a).TEXT_STRING().getText
                //val path =  arg.split(".").toList.asJava
                argList.add(arg)
            }

            add(  new Operation("minby",argList))


        }

        return "Success"
    }

    override def visitFunctionArg(ctx: ExprSyntaxParser.FunctionArgContext): Any = visitChildren(ctx)

    override def visitFunctionArgs(ctx: ExprSyntaxParser.FunctionArgsContext): Any = visitChildren(ctx)

    override def visitField_name(ctx: ExprSyntaxParser.Field_nameContext): Any = visitChildren(ctx)

}
